package com.beeasy.hzbpm.entity;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.github.llyb120.json.Arr;
import com.github.llyb120.json.Obj;
import org.bson.types.ObjectId;

import java.util.Collection;
import java.util.Date;
import java.util.List;

import static com.beeasy.hzbpm.bean.Util.getUserCacheName;
import static com.beeasy.hzbpm.bean.Util.getUserNamesMap;
import static com.github.llyb120.json.Json.*;

public class BpmInstance {

    //任务ID
    public ObjectId _id;

    //给人看的ID
    public String id;

    //任务状态
    public String state;

    //工作流xml模型
    public ObjectId bpmId;

    //原始名字
    public String bpmName;

    //用户ID
    public String pubUid;
    //用户名
    public String pubUName;

    //任务所属部门ID, 取用户所在部门ID，用符合授权的那一个，如果有多个符合的，选第一个
    public String depId;
    //任务所属部门名
    public String depName;

    //整理好的数据实体
    public BpmData bpmModel;

    public Date createTime;
    public Date lastModifyTime;

    //原始xml
    public String xml;

    public List<CurrentNode> currentNodes;


    public ObjectId parInsId;
    public String parLogId;


    //所有的属性集中在这里,直接初始化好,每当有人提交数据时，更新这个字段
    /**
     * {
     *     "字段1":"2017年10月10号",
     *     "$字段1"："ISODATE()"
     *     "字段2":"",
     *     "字段3":"",
     * }
     */
    public Obj attrs;
    private Obj oldAttrs = o();

    public Obj oldAttrs(){
        return oldAttrs;
    }
    public void oldAttrs(Obj attrs){
        this.oldAttrs.putAll(attrs);
    }

    public List<Sign> signs;

    // 批注
    public List<Comment> comments;

//    public List<AddonFile> files;

    //数据提交历史（记录）
    public List<DataLog> logs;

    // 待办理人
    public Obj todoUser;

    // 已办理人
    public Obj overUser;

//    public List<HandleLog> handleLogs;

    public static class DataLog{
        public String id;

        //当时所在的节点ID
        public String nodeId;
        public String nodeName;

        //提交到该节点上的信息，通常是节点名
        public String msg;

        //创建时间
        public Date time;

        //提交时间
        public Date startTime;
        public Date endTime;

        //确认时间
        public Date confirmTime;

        //提交人
        public String uid;
        public String uname;

//        public Map<String,String> aaaa;

        //日志类型
        public String type;

        //...
        //提交人是以什么身份进行提交的（当时这个节点的授权）

        //当时这个人提交的所有数据
//        public Map<String,Object> attrs;
        //新版数据
        public Arr attributes;

        public List<AddonFile> files;

        //用户还原当初的节点
        public Backup backup;

        public DataLog(){}

        public DataLog(BpmData.Node node, String type, String uid, String msg, Arr attrs, Arr files, CurrentNode currentNode){
            this(node,type,uid,msg,attrs,files);
            //关联currentNode
            currentNode.logId = id;
            backup = new BpmInstance.Backup(currentNode);
        }

        public DataLog(BpmData.Node node, String type, String uid, String msg, Arr attrs, Arr files){
            id = IdUtil.objectId();
            this.type = type;
            nodeId = node.id;
            nodeName = node.name;
            this.uid = uid;
            if(uid.equals("-1")){
                this.uname = "无主办人";
            } else {
                this.uname = getUserCacheName(uid);
            }
            time = startTime = endTime = new Date();
            confirmTime = null;
            this.msg = msg;
            if (files == null) {
                files = a();
            }
            this.files = aaa(files);
            this.attributes = attrs;
        }


        public static DataLog createEditLog(String uid, Arr attrs){
            DataLog log = new DataLog();
            log.nodeId = "-1";
            log.nodeName = "";
            log.type = "save";
            log.time = log.startTime = log.endTime = new Date();
            log.uid = uid;
            log.uname = getUserCacheName(uid);
            log.msg = "编辑";
            log.attributes = attrs;
            return log;
        }

        public static DataLog createBackLog(BpmData.Node node, String uid, String reason, String nodeName){
            DataLog log = new DataLog();
            log.uid = uid;
            log.uname = getUserCacheName(uid);
            log.type = "goBack";
            log.msg = String.format("<span style='color:red'>从【%s】回退节点到【%s】</span>", node.name, nodeName);
            log.time = log.startTime = log.endTime = new Date();
            log.attributes = a(a("原因", reason));
            log.nodeId = node.id;
            log.nodeName = node.name;
            return log;
        }
    }

    public static class Backup{
        //主办人
        public Obj mainUsers;
        //经办人
        public Obj supportUsers;

        public Backup(){}
        public Backup(CurrentNode currentNode){
            this.mainUsers = currentNode.mainUsers;
            this.supportUsers = currentNode.supportUsers;
        }
    }

//    public static class HandleLog{
//        public String nodeId;
//        public String nodeName;
//        public String uid;
//        public String uname;
//        public Date startDate;
//        public Date endDate;
//    }

    public static class CurrentNode {
        //当前节点的ID
        public String nodeId;
        public String nodeName;

        //提交到该节点上的信息，通常是节点名
        public String msg;

        //当前正在处理这个节点的人
//        public List<String> uids;
//        public List<String> unames;

        //主办人
        public Obj mainUsers;
        //经办人
        public Obj supportUsers;

        public String logId;

        // 当前时间
//        public Date nowTime;

        public Date minTimeout;
        public Date maxTimeout;
        // 超时提醒时间
//        public Date timeout;

        // 最大超时提醒时间
//        public Date maxTimeout;

        public CurrentNode(){}

        public CurrentNode(BpmData.Node node, Collection muids, Collection suids, DataLog dataLog) {
            this(node, muids, suids);
            //关联log
            logId = dataLog.id;
            dataLog.backup = new Backup(this);
        }

        public CurrentNode(BpmData.Node node, Collection muids, Collection suids) {
            nodeId = node.id;
            nodeName = node.name;
            mainUsers = getUserNamesMap(muids);
            supportUsers = getUserNamesMap(suids);


            //超时设置
            //以前的任务就不管他了
            try{
                //计算最小超时时间
                minTimeout = timeFormat(new Date(), node.timeout.minValue, node.timeout.minUnit);
                maxTimeout = timeFormat(new Date(), node.timeout.maxValue, node.timeout.maxUnit);
            } catch (Exception e){
            }
        }

        public Date timeFormat(Date date, int value, String unit){
            long time = date.getTime();
            switch (unit){
                case "分钟":
                    time += value * 60 * 1000;
                    break;

                case "秒":
                    time += value * 1000;
                    break;

                case "小时":
                    time += value * 3600 * 1000;
                    break;

                case "天":
                    time += value * 24 * 3600 * 1000;
                    break;
            }
            return new Date(time);
        }

        public boolean canDeal(String uid){
            try{
                return mainUsers.containsKey(uid) || supportUsers.containsKey(uid);
            } catch (Exception e){
                return false;
            }
        }



    }

    public static class Sign{
        public String nodeId;
        public String nodeName;
        public String uid;
        public String uname;
        public String idea;
        public String info;
//        public List<AddonFile> files;
        public Date created;
        public boolean over = false;
        public List files;
    }

    public static class Comment{
        public String uid;
        public String uname;
        public String content;
        public Date created;
        public int x;
        public int y;
    }


    public static class AddonFile{
        public String id;
        public String name;
        public String creator;
        public String action;

        @Override
        public boolean equals(Object obj) {
            return obj != null && (obj instanceof AddonFile && StrUtil.equals(((AddonFile)obj).id, id));
        }

        @Override
        public int hashCode() {
            return id.hashCode();
        }
    }
}
